﻿/*========================== 
 * @author 郑金泉
 * @desc 方法请求类
 * ========================= */
using System;
using System.Collections.Generic;
using System.Text;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Obsidian.Utils;
using Obsidian.Edm;

namespace Obsidian.Action
{
    public class ActionRequest
    {

        private string _action;
        private string _sessionKey;
        private ActionResponse _response;
        private List<ActReqParam> _listParams = new List<ActReqParam>();
        private Dictionary<string, ActReqParam> _dictParams = new Dictionary<string, ActReqParam>();

        /// <summary>
        /// 执行方法名称
        /// </summary>
        public string Action
        {
            get { return this._action; }
        }

        public string SessionKey
        {
            get { return this._sessionKey; }
        }

        /// <summary>
        /// 请求响应结果
        /// </summary>
        public ActionResponse Response
        {
            get { return this._response; }
        }

        /// <summary>
        /// 请求参数
        /// </summary>
        public Dictionary<string, ActReqParam> Params
        {
            get { return this._dictParams; }
        }

        public ActionRequest(string action)
        {
            if (String.IsNullOrEmpty(action))
                throw new Exception("action参数不能为空");
            this._action = action;
        }

        internal ActionRequest(JObject jo)
        {
            try
            {
                this._action = Convert.ToString(((JValue)jo["act"]).Value);
                JToken jtParams = jo["prms"];
                if (jtParams != null)
                {
                    JArray jarrParams = (JArray)jtParams;
                    foreach (JObject joParam in jarrParams)
                    {
                        ActReqParam arp = new ActReqParam(joParam);
                        this.AddParam(arp);
                    }
                }
            }
            catch (Exception ex) { throw ex; }
        }

        internal void SetSessionKey(string sessionKey)
        {
            this._sessionKey = sessionKey;
        }

        public void SetResponse(ActionResponse response)
        {
            this._response = response;
        }

        public ActionRequest AddParam(Dictionary<string, object> dict)
        {
            return this.AddParam(null, dict);
        }

        public ActionRequest AddParam(string name, Dictionary<string, object> dict)
        {
            List<string> fields = new List<string>();
            List<object> values = new List<object>();
            foreach (KeyValuePair<string, object> pair in dict)
            {
                fields.Add(pair.Key);
                values.Add(pair.Value);
            }
            ActReqParam param = new ActReqParam(name, fields.ToArray());
            param.AddValues(values.ToArray());
            this.AddParam(param);
            return this;
        }

        public ActionRequest AddParam(string fields, IModel model)
        {
            return this.AddParam(null, fields, model);
        }

        public ActionRequest AddParam(string name, string fields, IModel model)
        {
            return this.AddParam(name, fields, new List<IModel>() { model });
        }

        public ActionRequest AddParam(string fields, IList<IModel> models)
        {
            return this.AddParam(null, fields, models);
        }

        public ActionRequest AddParam(string name, string fields, IList<IModel> models)
        {
            if (String.IsNullOrEmpty(fields))
                throw new Exception("参数fields不能为空");
            string[] arrFields;
            if (fields == "*")
            {
                List<string> fieldList = new List<string>();
                IModel m = models[0];
                foreach (IModelField field in m.Fields)
                {
                    if (!string.IsNullOrEmpty(field.Alias))
                        fieldList.Add(field.Alias);
                }

                arrFields = fieldList.ToArray();
            }
            else
            {
                arrFields = fields.Split(',');
            }

            ActReqParam param = new ActReqParam(name, arrFields);
            param.AddModelList(models);
            this.AddParam(param);
            return this;
        }

        private void AddParam(ActReqParam arp)
        {
            string name = arp.Name;
            if (!String.IsNullOrEmpty(name))
                this._dictParams[name] = arp;
            this._listParams.Add(arp);
        }

        public ActReqParam GetFirstParam()
        {
            return this._listParams.Count > 0 ? this._listParams[0] : null;
        }

        public ActReqParam GetParam(string paramName)
        {
            return this._dictParams[paramName];
        }

        public ActReqParam GetParamByNameOrFirst(string paramName)
        {
            ActReqParam param;
            if (this._dictParams.TryGetValue(paramName, out param))
                return param;
            return this.GetFirstParam();
        }

        public bool TryGetParam(string paramName, out ActReqParam param)
        {
            return this._dictParams.TryGetValue(paramName, out param);
        }

        /// <summary>
        /// 获取第一个参数第一条数据转化为Model，当第参数为空时，不抛出异常
        /// </summary>
        /// <returns></returns>
        public T FirstModel<T>() where T : IModel, new()
        {
            if (this._listParams.Count == 0)
                return new T();
            else
            {
                ActReqParam arp = this._listParams[0];
                return arp.Count == 0 ? new T() : arp.ToModel<T>(0);
            }
        }

        /// <summary>
        /// 获取第一个参数第一条数据转化为Model，当第参数为空时，不抛出异常
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public T GetModel<T>(string paramName) where T : IModel, new()
        {
            ActReqParam param;
            if (!this.TryGetParam(paramName, out param))
                return new T();
            return param.Count == 0 ? new T() : param.ToModel<T>(0);
        }

        public T GetModelByNameOrFirst<T>(string paramName) where T : IModel, new()
        {
            ActReqParam param;
            if (this.TryGetParam(paramName, out param))
            {
                return param.Count == 0 ? new T() : param.ToModel<T>(0);
            }
            else
            {
                return this.FirstModel<T>();
            }
        }

        /// <summary>
        /// 获取第一个参数第一条数据转化为List，当第参数为空时，不抛出异常
        /// </summary>
        /// <returns></returns>
        public IList<T> FirstModelList<T>() where T : IModel, new()
        {
            if (this._listParams.Count == 0)
                return new List<T>();
            else
            {
                ActReqParam arp = this._listParams[0];
                return arp.ToModelList<T>();
            }
        }

        /// <summary>
        /// 获取第一个参数第一条数据转化为List，当第参数为空时，不抛出异常
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public IList<T> GetModelList<T>(string paramName) where T : IModel, new()
        {
            ActReqParam param;
            if (!this.TryGetParam(paramName, out param))
                return new List<T>();
            return param.ToModelList<T>();
        }

        public IList<T> GetModelListByNameOrFirst<T>(string paramName) where T : IModel, new()
        {
            ActReqParam param;
            if (this.TryGetParam(paramName, out param))
            {
                return param.ToModelList<T>();
            }
            else
            {
                return this.FirstModelList<T>();
            }
        }


        /// <summary>
        /// 获取第一个参数指定属性值
        /// </summary>
        /// <returns></returns>
        public bool TryGetValue(string name, out object val)
        {
            if (this._listParams.Count == 0)
            {
                val = -1;
                return false;
            }
            else
            {
                ActReqParam arp = this._listParams[0];
                return arp.TryGetValue(0, name, out val);
            }
        }
        /// <summary>
        /// 获取第一个参数指定属性值转化为String
        /// </summary>
        /// <returns></returns>
        public bool TryGetString(string name, out string val)
        {
            object o;
            if (!TryGetValue(name, out o))
            {
                val = null;
                return false;
            }
            val = Convert.ToString(o);
            return true;
        }
        /// <summary>
        /// 获取第一个参数指定属性值转化为Long
        /// </summary>
        /// <returns></returns>
        public bool TryGetLong(string name, out long val)
        {
            string str;
            if (!TryGetString(name, out str))
            {
                val = -1;
                return false;
            }
            return long.TryParse(str, out val);
        }
        /// <summary>
        /// 获取第一个参数指定属性值转化为Int
        /// </summary>
        /// <returns></returns>
        public bool TryGetInt(string name, out int val)
        {
            string str;
            if (!TryGetString(name, out str))
            {
                val = -1;
                return false;
            }
            return int.TryParse(str, out val);
        }

        public void WriteJson(JsonWriter jw)
        {
            jw.WriteStartObject();
            jw.WritePropertyName("act");
            jw.WriteValue(this._action);
            jw.WritePropertyName("prms");
            jw.WriteStartArray();
            foreach (ActReqParam param in this._listParams)
                param.WriteJson(jw);
            jw.WriteEndArray();
            jw.WriteEndObject();
        }

        //public IModel GetModel(ModelGene mg)
        //{
        //    IModel model = (IModel)mg.CreateModel();
        //    foreach (KeyValuePair<string, object> pair in this._dictParams)
        //    {
        //        string key = pair.Key;
        //        IModelField field = model.GetFieldByAlias(key);
        //        if (field != null)
        //            field.Set(pair.Value);
        //    }
        //    return model;
        //}



    }
}
